/**
 * @author Vitor Franco do Carmo (vitor.carmo@cpmbraxis.com)
 * @since 02/08/2013
 *
 */
package br.com.vfcfw.test;

import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;

import javax.inject.Inject;
import javax.sql.DataSource;

import org.dbunit.DBTestCase;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.DatabaseDataSourceConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ReplacementDataSet;
import org.dbunit.dataset.xml.FlatDtdDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.ext.oracle.OracleDataTypeFactory;
import org.dbunit.operation.DatabaseOperation;
import org.junit.runner.RunWith;

import br.com.vfcfw.commons.util.WeldUtil;

/**
 * Classe base para todos os testes unitários com acesso a base de dados que utilizam CDI para injeção de dependências.
 * 
 * @author Vitor Franco do Carmo (vitor.carmo@cpmbraxis.com)
 * @since 02/08/2013
 * 
 */
@RunWith(WeldJUnit4Runner.class)
public class BaseTesteIntegrado extends DBTestCase {

    private static final String PATH_DATASET = "dataSets/";

    private IDatabaseConnection connection;

    private IDataSet dataSet;

    private String xmlDatasetFileName;

    @Inject
    private DataSource dataSource;

    /**
     * Construtor da classe.
     * 
     * @param xmlDatasetFileName
     */
    public BaseTesteIntegrado(String xmlDatasetFileName) {

        super();
        this.xmlDatasetFileName = xmlDatasetFileName;
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.dbunit.DatabaseTestCase#setUp()
     */
    @Override
    protected void setUp() throws Exception {

        if (dataSource == null) {

            dataSource = WeldUtil.obterBeanParaTesteUnitario(DataSource.class);
        }
        connection = new DatabaseDataSourceConnection(dataSource, "NOME_BASE_DADOS");
        criarArquivoDTD(false);
        DatabaseOperation.REFRESH.execute(connection, getDataSet());
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.dbunit.DatabaseTestCase#tearDown()
     */
    @Override
    protected void tearDown() throws Exception {

        DatabaseOperation.DELETE_ALL.execute(connection, getDataSet());
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.dbunit.DatabaseTestCase#getSetUpOperation()
     */
    @Override
    protected DatabaseOperation getSetUpOperation() throws Exception {

        return DatabaseOperation.REFRESH;
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.dbunit.DatabaseTestCase#getTearDownOperation()
     */
    @Override
    protected DatabaseOperation getTearDownOperation() throws Exception {

        return DatabaseOperation.DELETE_ALL;
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.dbunit.DatabaseTestCase#getDataSet()
     */
    @Override
    protected IDataSet getDataSet() throws Exception {

        if (dataSet == null) {
            dataSet = new ReplacementDataSet(new FlatXmlDataSetBuilder().build(Thread.currentThread()
                .getContextClassLoader().getResourceAsStream(PATH_DATASET + xmlDatasetFileName)));

            connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new OracleDataTypeFactory());
            final byte[] replacementObjectBlob = criarObjetoSubstituicaoBlob();
            ((ReplacementDataSet) dataSet).addReplacementObject("BLOB", replacementObjectBlob);

        }

        return dataSet;

    }

    /**
     * Cria o objeto de substituição para o tipo blob.
     * 
     * @return Objeto de substituição.
     */
    private byte[] criarObjetoSubstituicaoBlob() {

        byte[] fakeFileData = { 't', 'e', 's', 't' };
        return fakeFileData;
    }

    /**
     * Cria o arquivo DTD dos Datasets.
     * 
     * @param criarDTD <tt>TRUE</tt> para criar o arquivo DTD, <tt>FALSE</tt> caso contrário.
     * @throws Exception
     */
    private void criarArquivoDTD(boolean criarDTD) throws Exception {

        if (criarDTD) {
            URL dirUrl = ClassLoader.getSystemResource(PATH_DATASET + xmlDatasetFileName);
            File fileDir = new File(dirUrl.toURI());
            String path = fileDir.getAbsolutePath().replace("\\", "/");
            File fileName = new File(path.substring(0, path.lastIndexOf("/")) + "/capfw-dbunit-dataset.dtd");
            FlatDtdDataSet.write(connection.createDataSet(), new FileOutputStream(fileName));
        }
    }

}
